int main (void) { pid_t childpid; char inbuf[MAX_CANON]; int len; for( ; ; ) { if (fputs(PROMPT_STRING, stdout) == EOF) continue; if (fgets(inbuf, MAX_CANON, stdin) == NULL) continue; len = strlen(inbuf); if (inbuf[len - 1] == '\n') inbuf[len - 1] = 0; if (strcmp(inbuf, QUIT_STRING) == 0) break; if ((childpid = fork()) == -1) perror("Failed to fork child"); else if (childpid == 0) { executecmd(inbuf); return 1; } else wait(NULL); } return 0; }
int main (void) { char *backp; sigset_t blockmask; pid_t childpid; struct sigaction defhandler; int inbackground; char inbuf[MAX_CANON]; int len; if (signalsetup(&defhandler, &blockmask, jumphd) == -1) { perror("Failed to set up shell signal handling"); return 1; } for( ; ; ) { if ((sigsetjmp(jumptoprompt, 1)) && /* if return from signal, newline */ (fputs("\n", stdout) == EOF) ) continue; okaytojump = 1; printf("%d",(int)getpid()); if (fputs(PROMPT_STRING, stdout) == EOF) continue; if (fgets(inbuf, MAX_CANON, stdin) == NULL) continue; len = strlen(inbuf); if (inbuf[len - 1] == '\n') inbuf[len - 1] = 0; if (strcmp(inbuf, QUIT_STRING) == 0) break; if ((backp = strchr(inbuf, BACK_SYMBOL)) == NULL) inbackground = 0; else { inbackground = 1; *backp = 0; } if (sigprocmask(SIG_BLOCK, &blockmask, NULL) == -1) perror("Failed to block signals"); if ((childpid = fork()) == -1) perror("Failed to fork"); else if (childpid == 0) { if (inbackground && (setpgid(0, 0) == -1)) return 1; if ((sigaction(SIGINT, &defhandler, NULL) == -1) || (sigaction(SIGQUIT, &defhandler, NULL) == -1) || (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1)) { perror("Failed to set signal handling for command "); return 1; } executecmd(inbuf); return 1; } if (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1) perror("Failed to unblock signals"); if (!inbackground) /* wait explicitly for the foreground process */ waitpid(childpid, NULL, 0); while (waitpid(-1, NULL, WNOHANG) > 0); /* wait for background procs */ } return 0; }
// =========================================================================== // METHOD: authdclient::setserviceonboot // =========================================================================== int authdclient::setserviceonboot (const string &servicename, bool enabled) { string command; command.printf ("setonboot \"%S\" %d\n", servicename.str(), (int) enabled); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::reloadservice // =========================================================================== int authdclient::reloadservice (const string &servicename) { string command; command.printf ("reloadservice \"%S\"\n", servicename.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::deluser // =========================================================================== int authdclient::deluser (const string &username) { string command; command.printf ("deleteuser \"%S\"\n", username.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::installfile // =========================================================================== int authdclient::installfile (const string &source, const string &dest) { string command; command.printf ("installfile \"%S\" \"%S\"\n", source.str(), dest.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::deletefile // =========================================================================== int authdclient::deletefile (const string &conffile) { string command; command.printf ("deletefile \"%S\"\n", conffile.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::setusershell // =========================================================================== int authdclient::setuserpass (const string &username, const string &password) { string command; command.printf ("setuserpass \"%S\" \"%S\"\n", username.str(), password.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::adduser // =========================================================================== int authdclient::adduser (const string &username, const string &shell, const string &passwd) { string command; command.printf ("createuser \"%S\" \"%S\"\n", username.str(), passwd.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::setusershell // =========================================================================== int authdclient::setusershell (const string &username, const string &shell) { string command; command.printf ("setusershell \"%S\" \"%S\"\n", username.str(), shell.str()); return executecmd (command); }
// =========================================================================== // METHOD: authdclient::setquota // =========================================================================== int authdclient::setquota (const string &username, unsigned int softlimit, unsigned int hardlimit) { string command; command.printf ("setquota \"%S\" %u %u\n", username.str(), softlimit, hardlimit); return executecmd (command); }
int builtin_exec_from_history(cmd_t* cmd, job_list_t* jobs, history_t* hist) { int index = (int) strtol(cmd->args[0], NULL, 10); cmd_t* past_cmd = get_from_history(hist, index); if (past_cmd) { cmd_t* new_cmd = copycmd(past_cmd); printcmd(new_cmd, stdout); return executecmd(new_cmd, jobs, hist); } return COMMAND_NOT_FOUND; }
int main (int argc, char **argv) { string user; //user name char* host = (char*)malloc(300); //host name if (getlogin() != NULL) { user = getlogin(); } else { perror("Error with getting user"); } if (gethostname(host, 300) == -1) { perror("Error with getting host name"); } //cout << host << endl; while (true) { BEGINNING: string cmd; string test = "test"; string bracket = "["; cout << user << "@" << host <<"$ "; getline(cin, cmd); parsing(cmd); if(AreParenBal(cmd) == false) { perror("Parenthesis not balanced\n"); goto BEGINNING; } char* b[MEMORY]; //character array that stores commands char command[MEMORY]; //char array that holds the converted command //cout << "Copying \n"; for(unsigned i =0; cmd[i] != '\0'; i++) { command[i] = cmd[i]; } command[cmd.length()] = '\0'; for (unsigned i = 0; command[i] != '\0'; i++) //outputs user input { cout << command[i]; } cout << endl; commandsort(command, b); queue<string> connectors; cout << "Executing commands\n"; executecmd(b, connectors); cout << "Executing done\n"; } free (host); return 0; }
int main() { char linea[MAXLEN]; int result=1; while(result) { printf("vshell > "); fflush(stdout); read(0,linea,80); locateend(linea); result=executecmd(linea); } }
int main (void) { sigset_t blockmask; pid_t childpid; struct sigaction defaction; char inbuf[MAX_CANON]; int len; if (signalsetup(&defaction, &blockmask, SIG_IGN) == -1) { perror("Failed to set up shell signal handling"); return 1; } if (sigprocmask(SIG_BLOCK, &blockmask, NULL) == -1) { perror("Failed to block signals"); return 1; } for( ; ; ) { if (fputs(PROMPT_STRING, stdout) == EOF) continue; if (fgets(inbuf, MAX_CANON, stdin) == NULL) continue; len = strlen(inbuf); if (inbuf[len - 1] == '\n') inbuf[len - 1] = 0; if (strcmp(inbuf, QUIT_STRING) == 0) break; if ((childpid = fork()) == -1) { perror("Failed to fork child to execute command"); } else if (childpid == 0) { if ((sigaction(SIGINT, &defaction, NULL) == -1) || (sigaction(SIGQUIT, &defaction, NULL) == -1) || (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1)) { perror("Failed to set signal handling for command "); return 1; } executecmd(inbuf); return 1; } wait(NULL); } return 0; }
int runLINK() { #if _WIN32 if (global.params.is64bit) { OutBuffer cmdbuf; cmdbuf.writestring("/NOLOGO "); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte(' '); const char *p = (*global.params.objfiles)[i]; const char *basename = FileName::removeExt(FileName::name(p)); const char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) { // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); } else writeFilename(&cmdbuf, p); FileName::free(basename); } if (global.params.resfile) { cmdbuf.writeByte(' '); writeFilename(&cmdbuf, global.params.resfile); } cmdbuf.writeByte(' '); if (global.params.exefile) { cmdbuf.writestring("/OUT:"); writeFilename(&cmdbuf, global.params.exefile); } else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ const char *n = (*global.params.objfiles)[0]; n = FileName::name(n); global.params.exefile = (char *)FileName::forceExt(n, "exe"); } // Make sure path to exe file exists ensurePathToNameExists(Loc(), global.params.exefile); cmdbuf.writeByte(' '); if (global.params.mapfile) { cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, global.params.mapfile); } else if (global.params.map) { const char *fn = FileName::forceExt(global.params.exefile, "map"); const char *path = FileName::path(global.params.exefile); const char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn); else p = fn; cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, p); } for (size_t i = 0; i < global.params.libfiles->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEFAULTLIB:"); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEF:"); writeFilename(&cmdbuf, global.params.deffile); } if (global.params.symdebug) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEBUG"); // in release mode we need to reactivate /OPT:REF after /DEBUG if (global.params.release) cmdbuf.writestring(" /OPT:REF"); } if (global.params.dll) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DLL"); } for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring((*global.params.linkswitches)[i]); } /* Append the path to the VC lib files, and then the SDK lib files */ const char *vcinstalldir = getenv("VCINSTALLDIR"); if (vcinstalldir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(vcinstalldir); cmdbuf.writestring("lib\\amd64\""); } const char *windowssdkdir = getenv("WindowsSdkDir"); if (windowssdkdir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(windowssdkdir); cmdbuf.writestring("lib\\x64\""); } char *p = cmdbuf.peekString(); const char *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(Loc(), "error writing file %s", lnkfilename); if (strlen(lnkfilename) < plen) sprintf(p, "@%s", lnkfilename); } const char *linkcmd = getenv("LINKCMD64"); if (!linkcmd) linkcmd = getenv("LINKCMD"); // backward compatible if (!linkcmd) { if (vcinstalldir) { OutBuffer linkcmdbuf; linkcmdbuf.writestring(vcinstalldir); linkcmdbuf.writestring("bin\\amd64\\link"); linkcmd = linkcmdbuf.extractString(); } else linkcmd = "link"; } int status = executecmd(linkcmd, p); if (lnkfilename) { remove(lnkfilename); FileName::free(lnkfilename); } return status; } else { OutBuffer cmdbuf; global.params.libfiles->push("user32"); global.params.libfiles->push("kernel32"); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); const char *p = (*global.params.objfiles)[i]; const char *basename = FileName::removeExt(FileName::name(p)); const char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) { // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); } else writeFilename(&cmdbuf, p); FileName::free(basename); } cmdbuf.writeByte(','); if (global.params.exefile) writeFilename(&cmdbuf, global.params.exefile); else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ const char *n = (*global.params.objfiles)[0]; n = FileName::name(n); global.params.exefile = (char *)FileName::forceExt(n, "exe"); } // Make sure path to exe file exists ensurePathToNameExists(Loc(), global.params.exefile); cmdbuf.writeByte(','); if (global.params.mapfile) writeFilename(&cmdbuf, global.params.mapfile); else if (global.params.map) { const char *fn = FileName::forceExt(global.params.exefile, "map"); const char *path = FileName::path(global.params.exefile); const char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn); else p = fn; writeFilename(&cmdbuf, p); } else cmdbuf.writestring("nul"); cmdbuf.writeByte(','); for (size_t i = 0; i < global.params.libfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(','); writeFilename(&cmdbuf, global.params.deffile); } /* Eliminate unnecessary trailing commas */ while (1) { size_t i = cmdbuf.offset; if (!i || cmdbuf.data[i - 1] != ',') break; cmdbuf.offset--; } if (global.params.resfile) { cmdbuf.writestring("/RC:"); writeFilename(&cmdbuf, global.params.resfile); } if (global.params.map || global.params.mapfile) cmdbuf.writestring("/m"); #if 0 if (debuginfo) cmdbuf.writestring("/li"); if (codeview) { cmdbuf.writestring("/co"); if (codeview3) cmdbuf.writestring(":3"); } #else if (global.params.symdebug) cmdbuf.writestring("/co"); #endif cmdbuf.writestring("/noi"); for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writestring((*global.params.linkswitches)[i]); } cmdbuf.writeByte(';'); char *p = cmdbuf.peekString(); const char *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(Loc(), "error writing file %s", lnkfilename); if (strlen(lnkfilename) < plen) sprintf(p, "@%s", lnkfilename); } const char *linkcmd = getenv("LINKCMD"); if (!linkcmd) linkcmd = "link"; int status = executecmd(linkcmd, p); if (lnkfilename) { remove(lnkfilename); FileName::free(lnkfilename); } return status; } #elif __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun pid_t childpid; int status; // Build argv[] Strings argv; const char *cc = getenv("CC"); if (!cc) cc = "gcc"; argv.push(cc); argv.insert(1, global.params.objfiles); #if __APPLE__ // If we are on Mac OS X and linking a dynamic library, // add the "-dynamiclib" flag if (global.params.dll) argv.push("-dynamiclib"); #elif __linux__ || __FreeBSD__ || __OpenBSD__ || __sun if (global.params.dll) argv.push("-shared"); #endif // None of that a.out stuff. Use explicit exe file name, or // generate one from name of first source file. argv.push("-o"); if (global.params.exefile) { argv.push(global.params.exefile); } else if (global.params.run) { #if 1 char name[L_tmpnam + 14 + 1]; strcpy(name, P_tmpdir); strcat(name, "/dmd_runXXXXXX"); int fd = mkstemp(name); if (fd == -1) { error(Loc(), "error creating temporary file"); return 1; } else close(fd); global.params.exefile = mem.strdup(name); argv.push(global.params.exefile); #else /* The use of tmpnam raises the issue of "is this a security hole"? * The hole is that after tmpnam and before the file is opened, * the attacker modifies the file system to get control of the * file with that name. I do not know if this is an issue in * this context. * We cannot just replace it with mkstemp, because this name is * passed to the linker that actually opens the file and writes to it. */ char s[L_tmpnam + 1]; char *n = tmpnam(s); global.params.exefile = mem.strdup(n); argv.push(global.params.exefile); #endif } else { // Generate exe file name from first obj name const char *n = (*global.params.objfiles)[0]; char *ex; n = FileName::name(n); const char *e = FileName::ext(n); if (e) { e--; // back up over '.' ex = (char *)mem.malloc(e - n + 1); memcpy(ex, n, e - n); ex[e - n] = 0; // If generating dll then force dll extension if (global.params.dll) ex = (char *)FileName::forceExt(ex, global.dll_ext); } else ex = (char *)"a.out"; // no extension, so give up argv.push(ex); global.params.exefile = ex; } // Make sure path to exe file exists ensurePathToNameExists(Loc(), global.params.exefile); if (global.params.symdebug) argv.push("-g"); if (global.params.is64bit) argv.push("-m64"); else argv.push("-m32"); if (global.params.map || global.params.mapfile) { argv.push("-Xlinker"); #if __APPLE__ argv.push("-map"); #else argv.push("-Map"); #endif if (!global.params.mapfile) { const char *fn = FileName::forceExt(global.params.exefile, "map"); const char *path = FileName::path(global.params.exefile); const char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn); else p = fn; global.params.mapfile = (char *)p; } argv.push("-Xlinker"); argv.push(global.params.mapfile); } if (0 && global.params.exefile) { /* This switch enables what is known as 'smart linking' * in the Windows world, where unreferenced sections * are removed from the executable. It eliminates unreferenced * functions, essentially making a 'library' out of a module. * Although it is documented to work with ld version 2.13, * in practice it does not, but just seems to be ignored. * Thomas Kuehne has verified that it works with ld 2.16.1. * BUG: disabled because it causes exception handling to fail * because EH sections are "unreferenced" and elided */ argv.push("-Xlinker"); argv.push("--gc-sections"); } for (size_t i = 0; i < global.params.linkswitches->dim; i++) { const char *p = (*global.params.linkswitches)[i]; if (!p || !p[0] || !(p[0] == '-' && (p[1] == 'l' || p[1] == 'L'))) // Don't need -Xlinker if switch starts with -l or -L. // Eliding -Xlinker is significant for -L since it allows our paths // to take precedence over gcc defaults. argv.push("-Xlinker"); argv.push(p); } /* Add each library, prefixing it with "-l". * The order of libraries passed is: * 1. any libraries passed with -L command line switch * 2. libraries specified on the command line * 3. libraries specified by pragma(lib), which were appended * to global.params.libfiles. * 4. standard libraries. */ for (size_t i = 0; i < global.params.libfiles->dim; i++) { const char *p = (*global.params.libfiles)[i]; size_t plen = strlen(p); if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') argv.push(p); else { char *s = (char *)mem.malloc(plen + 3); s[0] = '-'; s[1] = 'l'; memcpy(s + 2, p, plen + 1); argv.push(s); } } for (size_t i = 0; i < global.params.dllfiles->dim; i++) { const char *p = (*global.params.dllfiles)[i]; argv.push(p); } /* Standard libraries must go after user specified libraries * passed with -l. */ const char *libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; size_t slen = strlen(libname); if (slen) { char *buf = (char *)malloc(3 + slen + 1); strcpy(buf, "-l"); /* Use "-l:libname.a" if the library name is complete */ if (slen > 3 + 2 && memcmp(libname, "lib", 3) == 0 && (memcmp(libname + slen - 2, ".a", 2) == 0 || memcmp(libname + slen - 3, ".so", 3) == 0) ) { strcat(buf, ":"); } strcat(buf, libname); argv.push(buf); // turns into /usr/lib/libphobos2.a } #ifdef __sun argv.push("-mt"); #endif // argv.push("-ldruntime"); argv.push("-lpthread"); argv.push("-lm"); #if __linux__ // Changes in ld for Ubuntu 11.10 require this to appear after phobos2 argv.push("-lrt"); #endif if (global.params.verbose) { // Print it for (size_t i = 0; i < argv.dim; i++) fprintf(global.stdmsg, "%s ", argv[i]); fprintf(global.stdmsg, "\n"); } argv.push(NULL); // set up pipes int fds[2]; if (pipe(fds) == -1) { perror("Unable to create pipe to linker"); return -1; } childpid = fork(); if (childpid == 0) { // pipe linker stderr to fds[0] dup2(fds[1], STDERR_FILENO); close(fds[0]); execvp(argv[0], (char **)argv.tdata()); perror(argv[0]); // failed to execute return -1; } else if (childpid == -1) { perror("Unable to fork"); return -1; } close(fds[1]); const int nme = findNoMainError(fds[0]); waitpid(childpid, &status, 0); if (WIFEXITED(status)) { status = WEXITSTATUS(status); if (status) { if (nme == -1) { perror("Error with the linker pipe"); return -1; } else { printf("--- errorlevel %d\n", status); if (nme == 1) error(Loc(), "no main function specified"); } } } else if (WIFSIGNALED(status)) { printf("--- killed by signal %d\n", WTERMSIG(status)); status = 1; } return status; #else printf ("Linking is not yet supported for this version of DMD.\n"); return -1; #endif }
int main (void) { char *backp; sigset_t blockmask; pid_t childpid; struct sigaction defhandler; int inbackground; int len; char inbuf[MAX_CANON]; if (signalsetup(&defhandler, &blockmask, jumphd) == -1) { perror("Failed to set up shell signal handling"); return 1; } for( ; ; ) { if ((sigsetjmp(jumptoprompt, 1)) && /* if return from signal, \n */ (fputs("\n", stdout) == EOF) ) continue; okaytojump = 1; printf("%d",(int)getpid()); if (fputs(PROMPT_STRING, stdout) == EOF) continue; if (fgets(inbuf, MAX_CANON, stdin) == NULL) continue; len = strlen(inbuf); if (inbuf[len - 1] == '\n') inbuf[len - 1] = 0; if (strcmp(inbuf, QUIT_STRING) == 0) break; if ((backp = strchr(inbuf, BACK_SYMBOL)) == NULL) inbackground = 0; else { inbackground = 1; *backp = 0; } if (sigprocmask(SIG_BLOCK, &blockmask, NULL) == -1) perror("Failed to block signals"); if ((childpid = fork()) == -1) perror("Failed to fork"); else if (childpid == 0) { if (inbackground) { /* child creates another process */ if ((childpid = fork()) == -1) { perror("Second fork failed"); return 1; } if (childpid > 0) return 0; if (setpgid(0, 0) == -1) { perror("setpgod failed"); return 1; } } if ((sigaction(SIGINT, &defhandler, NULL) < 0) || (sigaction(SIGQUIT, &defhandler, NULL) < 0) || (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1)) { perror("Failed to set signal handling for command "); return 1; } executecmd(inbuf); perror("Failed to execute command"); return 1; } if (sigprocmask(SIG_UNBLOCK, &blockmask, NULL) == -1) perror("Failed to unblock signals"); wait(NULL); } return 0; }
int runLINK() { #if _WIN32 if (global.params.is64bit) { OutBuffer cmdbuf; for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte(' '); char *p = (*global.params.objfiles)[i]; char *basename = FileName::removeExt(FileName::name(p)); char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); else writeFilename(&cmdbuf, p); mem.free(basename); } if (global.params.resfile) { cmdbuf.writeByte(' '); writeFilename(&cmdbuf, global.params.resfile); } cmdbuf.writeByte(' '); if (global.params.exefile) { cmdbuf.writestring("/OUT:"); writeFilename(&cmdbuf, global.params.exefile); } else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ char *n = (*global.params.objfiles)[0]; n = FileName::name(n); FileName *fn = FileName::forceExt(n, "exe"); global.params.exefile = fn->toChars(); } // Make sure path to exe file exists { char *p = FileName::path(global.params.exefile); FileName::ensurePathExists(p); mem.free(p); } cmdbuf.writeByte(' '); if (global.params.mapfile) { cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, global.params.mapfile); } else if (global.params.map) { FileName *fn = FileName::forceExt(global.params.exefile, "map"); char *path = FileName::path(global.params.exefile); char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn->toChars()); else p = fn->toChars(); cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, p); } for (size_t i = 0; i < global.params.libfiles->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEFAULTLIB:"); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEF:"); writeFilename(&cmdbuf, global.params.deffile); } if (global.params.symdebug) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEBUG"); } if (global.params.dll) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DLL"); } cmdbuf.writestring(" /MERGE:.minfobg=.minfodt /MERGE:.minfoen=.minfodt"); cmdbuf.writestring(" /MERGE:._deh_bg=._deh_eh /MERGE:._deh_en=._deh_eh"); for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring((*global.params.linkswitches)[i]); } /* Append the path to the VC lib files, and then the SDK lib files */ const char *vcinstalldir = getenv("VCINSTALLDIR"); if (vcinstalldir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(vcinstalldir); cmdbuf.writestring("lib\\amd64\""); } const char *windowssdkdir = getenv("WindowsSdkDir"); if (windowssdkdir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(windowssdkdir); cmdbuf.writestring("lib\\x64\""); } char *p = cmdbuf.toChars(); FileName *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(0, "error writing file %s", lnkfilename); if (lnkfilename->len() < plen) sprintf(p, "@%s", lnkfilename->toChars()); } char *linkcmd = getenv("LINKCMD"); if (!linkcmd) { if (vcinstalldir) { OutBuffer linkcmdbuf; linkcmdbuf.writestring(vcinstalldir); linkcmdbuf.writestring("bin\\amd64\\link"); linkcmd = linkcmdbuf.toChars(); linkcmdbuf.extractData(); } else linkcmd = "link"; } int status = executecmd(linkcmd, p, 1); if (lnkfilename) { remove(lnkfilename->toChars()); delete lnkfilename; } return status; } else { OutBuffer cmdbuf; global.params.libfiles->push("user32"); global.params.libfiles->push("kernel32"); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); char *p = (*global.params.objfiles)[i]; char *basename = FileName::removeExt(FileName::name(p)); char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); else writeFilename(&cmdbuf, p); mem.free(basename); } cmdbuf.writeByte(','); if (global.params.exefile) writeFilename(&cmdbuf, global.params.exefile); else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ char *n = (*global.params.objfiles)[0]; n = FileName::name(n); FileName *fn = FileName::forceExt(n, "exe"); global.params.exefile = fn->toChars(); } // Make sure path to exe file exists { char *p = FileName::path(global.params.exefile); FileName::ensurePathExists(p); mem.free(p); } cmdbuf.writeByte(','); if (global.params.mapfile) writeFilename(&cmdbuf, global.params.mapfile); else if (global.params.map) { FileName *fn = FileName::forceExt(global.params.exefile, "map"); char *path = FileName::path(global.params.exefile); char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn->toChars()); else p = fn->toChars(); writeFilename(&cmdbuf, p); } else cmdbuf.writestring("nul"); cmdbuf.writeByte(','); for (size_t i = 0; i < global.params.libfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(','); writeFilename(&cmdbuf, global.params.deffile); } /* Eliminate unnecessary trailing commas */ while (1) { size_t i = cmdbuf.offset; if (!i || cmdbuf.data[i - 1] != ',') break; cmdbuf.offset--; } if (global.params.resfile) { cmdbuf.writestring("/RC:"); writeFilename(&cmdbuf, global.params.resfile); } if (global.params.map || global.params.mapfile) cmdbuf.writestring("/m"); #if 0 if (debuginfo) cmdbuf.writestring("/li"); if (codeview) { cmdbuf.writestring("/co"); if (codeview3) cmdbuf.writestring(":3"); } #else if (global.params.symdebug) cmdbuf.writestring("/co"); #endif cmdbuf.writestring("/noi"); for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writestring((*global.params.linkswitches)[i]); } cmdbuf.writeByte(';'); char *p = cmdbuf.toChars(); FileName *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(0, "error writing file %s", lnkfilename); if (lnkfilename->len() < plen) sprintf(p, "@%s", lnkfilename->toChars()); } char *linkcmd = getenv("LINKCMD"); if (!linkcmd) linkcmd = "link"; int status = executecmd(linkcmd, p, 1); if (lnkfilename) { remove(lnkfilename->toChars()); delete lnkfilename; } return status; } #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun pid_t childpid; int status; // Build argv[] Strings argv; const char *cc = getenv("CC"); if (!cc) cc = "gcc"; argv.push((char *)cc); argv.insert(1, global.params.objfiles); #if __APPLE__ // If we are on Mac OS X and linking a dynamic library, // add the "-dynamiclib" flag if (global.params.dll) argv.push((char *) "-dynamiclib"); #elif linux || __FreeBSD__ || __OpenBSD__ || __sun if (global.params.dll) argv.push((char *) "-shared"); #endif // None of that a.out stuff. Use explicit exe file name, or // generate one from name of first source file. argv.push((char *)"-o"); if (global.params.exefile) { if (global.params.dll) global.params.exefile = FileName::forceExt(global.params.exefile, global.dll_ext)->toChars(); argv.push(global.params.exefile); } else { // Generate exe file name from first obj name char *n = (*global.params.objfiles)[0]; char *e; char *ex; n = FileName::name(n); e = FileName::ext(n); if (e) { e--; // back up over '.' ex = (char *)mem.malloc(e - n + 1); memcpy(ex, n, e - n); ex[e - n] = 0; // If generating dll then force dll extension if (global.params.dll) ex = FileName::forceExt(ex, global.dll_ext)->toChars(); } else ex = (char *)"a.out"; // no extension, so give up argv.push(ex); global.params.exefile = ex; } // Make sure path to exe file exists { char *p = FileName::path(global.params.exefile); FileName::ensurePathExists(p); mem.free(p); } if (global.params.symdebug) argv.push((char *)"-g"); if (global.params.is64bit) argv.push((char *)"-m64"); else argv.push((char *)"-m32"); if (global.params.map || global.params.mapfile) { argv.push((char *)"-Xlinker"); #if __APPLE__ argv.push((char *)"-map"); #else argv.push((char *)"-Map"); #endif if (!global.params.mapfile) { FileName *fn = FileName::forceExt(global.params.exefile, "map"); char *path = FileName::path(global.params.exefile); char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn->toChars()); else p = fn->toChars(); global.params.mapfile = p; } argv.push((char *)"-Xlinker"); argv.push(global.params.mapfile); } if (0 && global.params.exefile) { /* This switch enables what is known as 'smart linking' * in the Windows world, where unreferenced sections * are removed from the executable. It eliminates unreferenced * functions, essentially making a 'library' out of a module. * Although it is documented to work with ld version 2.13, * in practice it does not, but just seems to be ignored. * Thomas Kuehne has verified that it works with ld 2.16.1. * BUG: disabled because it causes exception handling to fail * because EH sections are "unreferenced" and elided */ argv.push((char *)"-Xlinker"); argv.push((char *)"--gc-sections"); } for (size_t i = 0; i < global.params.linkswitches->dim; i++) { char *p = (*global.params.linkswitches)[i]; if (!p || !p[0] || !(p[0] == '-' && (p[1] == 'l' || p[1] == 'L'))) // Don't need -Xlinker if switch starts with -l or -L. // Eliding -Xlinker is significant for -L since it allows our paths // to take precedence over gcc defaults. argv.push((char *)"-Xlinker"); argv.push(p); } /* Add each library, prefixing it with "-l". * The order of libraries passed is: * 1. any libraries passed with -L command line switch * 2. libraries specified on the command line * 3. libraries specified by pragma(lib), which were appended * to global.params.libfiles. * 4. standard libraries. */ for (size_t i = 0; i < global.params.libfiles->dim; i++) { char *p = (*global.params.libfiles)[i]; size_t plen = strlen(p); if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') argv.push(p); else { char *s = (char *)mem.malloc(plen + 3); s[0] = '-'; s[1] = 'l'; memcpy(s + 2, p, plen + 1); argv.push(s); } } /* Standard libraries must go after user specified libraries * passed with -l. */ const char *libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; size_t slen = strlen(libname); if (slen) { char *buf = (char *)malloc(2 + slen + 1); strcpy(buf, "-l"); strcpy(buf + 2, libname); argv.push(buf); // turns into /usr/lib/libphobos2.a } #ifdef __sun argv.push((char *)"-mt"); #endif // argv.push((void *)"-ldruntime"); argv.push((char *)"-lpthread"); argv.push((char *)"-lm"); #if linux && DMDV2 // Changes in ld for Ubuntu 11.10 require this to appear after phobos2 argv.push((char *)"-lrt"); #endif if (!global.params.quiet || global.params.verbose) { // Print it for (size_t i = 0; i < argv.dim; i++) printf("%s ", argv[i]); printf("\n"); fflush(stdout); } argv.push(NULL); #if HAS_POSIX_SPAWN int spawn_err = posix_spawnp(&childpid, argv[0], NULL, NULL, argv.tdata(), environ); if (spawn_err != 0) { perror(argv[0]); return -1; } #else childpid = fork(); if (childpid == 0) { execvp(argv[0], argv.tdata()); perror(argv[0]); // failed to execute return -1; } else if (childpid == -1) { perror("Unable to fork"); return -1; } #endif waitpid(childpid, &status, 0); if (WIFEXITED(status)) { status = WEXITSTATUS(status); if (status) printf("--- errorlevel %d\n", status); } else if (WIFSIGNALED(status)) { printf("--- killed by signal %d\n", WTERMSIG(status)); status = 1; } return status; #else printf ("Linking is not yet supported for this version of DMD.\n"); return -1; #endif }
int runLINK() { #if _WIN32 char *p; int i; int status; OutBuffer cmdbuf; global.params.libfiles->push((void *) "user32"); global.params.libfiles->push((void *) "kernel32"); for (i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); p = (char *)global.params.objfiles->data[i]; char *ext = FileName::ext(p); if (ext) cmdbuf.write(p, ext - p - 1); else cmdbuf.writestring(p); } cmdbuf.writeByte(','); if (global.params.exefile) cmdbuf.writestring(global.params.exefile); else { // Generate exe file name from first obj name char *n = (char *)global.params.objfiles->data[0]; char *ex; n = FileName::name(n); FileName *fn = FileName::forceExt(n, "exe"); global.params.exefile = fn->toChars(); } cmdbuf.writeByte(','); if (global.params.run) cmdbuf.writestring("nul"); // if (mapfile) // cmdbuf.writestring(output); cmdbuf.writeByte(','); for (i = 0; i < global.params.libfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); cmdbuf.writestring((char *) global.params.libfiles->data[i]); } if (global.params.deffile) { cmdbuf.writeByte(','); cmdbuf.writestring(global.params.deffile); } /* Eliminate unnecessary trailing commas */ while (1) { i = cmdbuf.offset; if (!i || cmdbuf.data[i - 1] != ',') break; cmdbuf.offset--; } if (global.params.resfile) { cmdbuf.writestring("/RC:"); cmdbuf.writestring(global.params.resfile); } #if 0 if (mapfile) cmdbuf.writestring("/m"); if (debuginfo) cmdbuf.writestring("/li"); if (codeview) { cmdbuf.writestring("/co"); if (codeview3) cmdbuf.writestring(":3"); } #else if (global.params.symdebug) cmdbuf.writestring("/co"); #endif cmdbuf.writestring("/noi"); for (i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writestring((char *) global.params.linkswitches->data[i]); } cmdbuf.writeByte(';'); p = cmdbuf.toChars(); char *linkcmd = getenv("LINKCMD"); if (!linkcmd) linkcmd = "link"; status = executecmd(linkcmd, p, 1); return status; #elif linux pid_t childpid; int i; int status; // Build argv[] Array argv; char *cc = getenv("CC"); if (!cc) cc = "gcc"; argv.push((void *)cc); argv.insert(1, global.params.objfiles); // None of that a.out stuff. Use explicit exe file name, or // generate one from name of first source file. argv.push((void *)"-o"); if (global.params.exefile) { argv.push(global.params.exefile); } else { // Generate exe file name from first obj name char *n = (char *)global.params.objfiles->data[0]; char *e; char *ex; n = FileName::name(n); e = FileName::ext(n); if (e) { e--; // back up over '.' ex = (char *)mem.malloc(e - n + 1); memcpy(ex, n, e - n); ex[e - n] = 0; } else ex = (char *)"a.out"; // no extension, so give up argv.push(ex); global.params.exefile = ex; } argv.insert(argv.dim, global.params.libfiles); if (global.params.symdebug) argv.push((void *)"-g"); argv.push((void *)"-m32"); argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a argv.push((void *)"-lpthread"); argv.push((void *)"-lm"); if (0 && global.params.exefile) { /* This switch enables what is known as 'smart linking' * in the Windows world, where unreferenced sections * are removed from the executable. It eliminates unreferenced * functions, essentially making a 'library' out of a module. * Although it is documented to work with ld version 2.13, * in practice it does not, but just seems to be ignored. * Thomas Kuehne has verified that it works with ld 2.16.1. * BUG: disabled because it causes exception handling to fail */ argv.push((void *)"-Xlinker"); argv.push((void *)"--gc-sections"); } for (i = 0; i < global.params.linkswitches->dim; i++) { argv.push((void *)"-Xlinker"); argv.push((void *) global.params.linkswitches->data[i]); } if (!global.params.quiet) { // Print it for (i = 0; i < argv.dim; i++) printf("%s ", (char *)argv.data[i]); printf("\n"); fflush(stdout); } argv.push(NULL); childpid = fork(); if (childpid == 0) { execvp((char *)argv.data[0], (char **)argv.data); perror((char *)argv.data[0]); // failed to execute return -1; } waitpid(childpid, &status, 0); status=WEXITSTATUS(status); if (status) printf("--- errorlevel %d\n", status); return status; #else printf ("Linking is not yet supported for this version of DMD.\n"); return -1; #endif }