home *** CD-ROM | disk | FTP | other *** search
- /*
- * make.c An imitation of the Unix MAKE facility
- *
- * 88-10-01 v1.0 created by greg yachuk, placed in the public domain
- * 88-10-06 v1.1 changed prerequisite list handling
- * 88-11-17 v1.2 AB added lots of options
- * 89-04-30 v1.3 AB added environment flag MAKEFLAGS=
- * 89-06-16 v1.4 AB lib response file not working
- *
- */
-
- #include <stdio.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
- #include <memory.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef MSDOS
- #include <stdlib.h>
- #include <process.h>
- #include <dos.h>
- #include <io.h>
- #include <direct.h>
- #else
- #include <sys/errno.h>
- #include <sys/wait.h>
- #endif
-
- #include "make.h"
- #include "tstring.h"
- #include "decl.h"
-
-
- #ifdef MSDOS
- #define PATH_SEPARATOR ";"
- #define FILE_SEPARATOR "/\\"
- #define RD_PERM 4 /* access() function */
- #else
- #define PATH_SEPARATOR ":"
- #define FILE_SEPARATOR "/"
- #define RD_PERM 4 /* access() function */
- #endif
-
- #define MAKEINI "default.mk"
-
- char **resp_cmds; /* .RESPONSE commands */
- char *shell_cmds[] = {
- #ifdef MSDOS
- "dir", "type", "rem", "pause", "date", "time", "ren", "rename",
- "ver", "vol", "break", "verify", "mkdir", "md", "exit", "ctty",
- "echo", "if", "cls", "chdir", "cd", "rmdir", "rd", "copy", "del",
- "erase", "set", "for", "prompt", "path",
- #endif
- NULL,
- };
-
- char *makelist[] = /* List of possible makefile names */
- {
- "makefile",
- "Makefile",
- NULL
- };
-
- char *usage_str[] =
- {
- #ifdef MSDOS
- "Make v1.4 (DOS version)\n",
- #else
- "Make v1.4\n",
- #endif
- "Usage : make [-f filename] [-CdeiknrstFV] [target ...] [macro = value ...]",
- "",
- "Options:",
- "",
- " -f the next argument is the name of a makefile",
- " -C force forking shell for building target",
- " -d show target dependencies",
- "! -D show text of makefile",
- " -e environment variables override macro assignments",
- " -F force target updates",
- " -i ignore error codes retunred by commands",
- " -k abandon building current target, continue with other targets",
- " -n don't execute, list actions",
- "! -p print out macro definitions and target description",
- "! -P print out macro definitions and target description",
- "! -q question mode, make returns zero or nonzero status code",
- " -r don't use builtin rules",
- " -s run silently without listing actions",
- " -S undo the effect of the -k option",
- " -t touch the target files (bring them up to date)",
- " -V list the current program version",
- "",
- "",
- "Macro usage:",
- ".DEFAULT - define default rule to build target",
- ".DONE - target to build, after all other targets are build",
- ".IGNORE - ignore all error codes during building of targets",
- ".INIT - first target to build, before any target is build",
- ".SILENT - do not echo commands",
- ".RESPONSE - define a response file for long ( > 128) command lines",
- ".SUFFIXES - the suffixes list for selecting implicit rules",
- NULL
- };
-
- static char **version = &usage_str[0];
-
-
- targptr target_list; /* list of target nodes */
- fileptr file_list; /* list of file nodes */
- symptr symbol_list; /* list of symbol nodes */
- shellptr shell_list; /* list of shell nodes */
-
- targptr first_targ = NULL; /* first target, in case nothing explicit */
- targptr suffix_targ = NULL; /* .SUFFIXES target pointer */
-
- char **tlist = NULL; /* command line targets */
- char **flist = NULL; /* command line make files */
- char **mlist = NULL; /* command line macros */
-
- int tmax = 0; /* max size of tlist */
- int fmax = 0; /* max size of flist */
- int mmax = 0; /* max size of mlist */
-
- short forceshell = 0; /* -C option */
- short debug = 0; /* -d option */
- short touchenv = 1; /* -e option */
- short ignore = 0; /* -i option */
- short single_ign = 0; /* -k option */
- short noexec = 0; /* -n option */
- short silent = 0; /* -s option */
- short touch = 0; /* -t option */
- short readdef = 1; /* -r option */
- short depend = 0; /* -D option */
- short force = 0; /* -F option */
-
- long now; /* time at startup */
-
- #ifndef MSDOS
- static void _searchenv();
- #endif
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- REGISTER int i;
- REGISTER targptr targp;
- targptr resp_targ; /* file list for long command lines>response file */
- int done = 0;
- char **makefile;
- char *mk, *envargs, **eargv;
-
- /* get current date & time */
-
- now = curr_time();
-
- /* initialize the various global lists */
-
- target_list = NULL;
- file_list = NULL;
- symbol_list = NULL;
- shell_list = NULL;
-
- /* allocate space for command line targets, files and macros */
-
- tlist = grow_list(NULL, &tmax);
- flist = grow_list(NULL, &fmax);
- mlist = grow_list(NULL, &mmax);
-
- add_symbol("MAKE", "make"); /* Default $(MAKE) macro */
-
- if ( (envargs = getenv("MAKEFLAGS")) )
- {
- eargv = tokenize(tstrcpy(envargs));
- make_args(-1, eargv);
- tfree(eargv);
- }
-
- make_args(--argc, ++argv); /* process command line options */
-
- if (noexec)
- silent = touch = 0; /* -n always displays; never touches */
-
- first_targ = NULL; /* used in parse() */
-
- if (readdef)
- parse(fopenp(MAKEINI, "r"), 0); /* read in `default.mk' */
-
- first_targ = NULL; /* get first target in `makefile' */
-
- /* parse the makefiles given on command line */
- for(i = 0; flist[i] != NULL; i++)
- parse(fopen(flist[i], "r"), 0);
-
- /* no makefiles specified, so use "makefile" */
- if (i == 0)
- {
- for ( makefile = makelist; !done && *makefile; makefile++ )
- {
- if ( debug > 1 )
- printf("*** Accessing makefile '%s'\n", *makefile);
- if ( (done = !access(*makefile, RD_PERM)) )
- {
- if ( debug )
- printf("*** Reading %s\n", *makefile);
- parse(fopen(*makefile, "r"), 0);
- }
- }
- }
-
- tfree(flist); /* all done with makefile's */
-
- for(i = 0; mlist[i] != NULL; i++)
- add_macro(mlist[i]); /* add command line macros */
-
- tfree(mlist); /* all done with macros */
-
- if ( (resp_targ = get_target(".RESPONSE")) )
- resp_cmds = tokenize(breakout((*resp_targ->tshell)->scmd));
-
- if ((targp = get_target(".INIT")) != NULL)
- build(targp->tshell); /* process the .INIT rule */
-
- for (i = 0; tlist[i] != NULL; i++)
- make(tlist[i], 1); /* process command line targets */
-
- tfree(tlist); /* all done with targets */
-
- /* if no targets specified, make the first one */
- if (i == 0 && first_targ)
- make(first_targ->tfile->fname, 1);
-
- if ((targp = get_target(".DONE")) != NULL)
- build(targp->tshell); /* process the .DONE rule */
-
- return (0); /* not exit(); see new_make() */
- }
-
- /* decode all command line & environment options */
- /* no -f option accepted from env, argc set neg */
-
- make_args(argc, argv)
- int argc;
- char **argv;
- {
- static int tlen = 0;
- static int flen = 0;
- static int mlen = 0;
- char no_k = 0;
-
- for ( ; *argv && argc; *(++argv) && --argc )
- {
- /* look for macros and targets */
- if ( **argv != '-' )
- {
- if ( strchr(*argv, '=') )
- { /* store as a macro */
- if (mlen == mmax)
- mlist = grow_list(mlist, &mmax);
- mlist[mlen++] = *argv;
- }
- else
- { /* store as a target */
- if ( tlen == tmax )
- tlist = grow_list(tlist, &tmax);
- tlist[tlen++] = *argv;
- }
- continue;
- }
-
- while ( *argv && *++*argv )
- {
- switch (**argv)
- {
- case 'C': /* force shell forking for target */
- forceshell = 1;
- break;
-
- case 'd': /* show dependencies */
- if ( isdigit(*(*argv + 1)) )
- debug = *++*argv;
- else
- debug++;
- break;
-
- case 'e': /* environment overrides assignments */
- touchenv = 0;
- break;
-
- case 'f': /* new makefile name */
- if ( argc > 0 )
- {
- if (argc < 2)
- usage();
- if (flen == fmax)
- flist = grow_list(flist, &fmax);
- flist[flen++] = *(++argv);
- }
- else
- {
- printf("Illegal -f option in environment, ignored\n");
- ++argv;
- }
- --argc;
- *argv = NULL;
- break;
-
- case 'i': /* ignore errors */
- ignore = 1;
- break;
-
- case 'k': /* ignore single target errors only */
- single_ign = 1;
- break;
-
- case 'n': /* don't execute commands */
- noexec = 1;
- break;
-
- case 'r': /* don't read default.mk */
- readdef = 0;
- break;
-
- case 's': /* don't echo commands */
- silent = 1;
- break;
-
- case 'S': /* undo the -k option */
- no_k = 1;
- break;
-
- case 't': /* touch files, don't build */
- touch = 1;
- break;
-
- case 'D': /* display makefiles */
- depend = 1;
- break;
-
- case 'F': /* ignore target date, force make */
- force = 1;
- break;
-
- case 'V': /* ignore target date, force make */
- puts(*version);
- break;
-
- default:
- usage();
- }
- }
- }
-
- if ( no_k )
- single_ign = 0;
-
- /* terminate all lists with a NULL pointer */
-
- tlist[tlen] = NULL;
- flist[flen] = NULL;
- mlist[mlen] = NULL;
- }
-
-
- /*
- * grow_list - expand the list of pointers by a factor of two
- */
- char **grow_list(list, len)
- char **list;
- int *len;
- {
- REGISTER int l;
-
- l = *len; /* get current length */
-
- /* if list is NULL, start off with a default list */
-
- if ( list == NULL )
- list = (char **)talloc(((l=1)+1) * sizeof(char *));
- else
- list = (char **) trealloc((char *)list, ((l <<=1)+1)*sizeof(char *));
-
- if ( list == NULL )
- terror(1, "too many options");
-
- /* if we are initially allocating it, set first pointer to NULL */
-
- if ( l == 1 )
- *list = NULL;
-
- *len = l; /* update current length */
- return (list);
- }
-
-
- /*
- * fopenp - open file in current directory or along PATH
- */
- FILE *fopenp(fname, type)
- char *fname;
- char *type;
- {
- REGISTER int len;
- REGISTER char *fpath;
- FILE *fd;
-
- /* if the filename is -, use stdin */
- if (equal(fname, "-"))
- return (stdin);
-
- fpath = talloc(256 + strlen(fname) + 2);
-
- _searchenv(fname, "PATH", fpath);
-
- /* try to open file relative to current directory */
-
- if ( (fd = fopen(fpath, type)) != NULL && debug )
- printf("*** Reading default rules from %s\n", fpath);
-
- tfree(fpath);
-
- return (fd);
- }
-
- #ifndef MSDOS
- void _searchenv(fname, env, fpath)
- char *fname, *env, *fpath;
- {
- char *path;
- char *tp;
-
- *fpath = '\0';
-
- if ((path = getenv(env)) == NULL)
- return;
-
- path = tstrcpy(path); /* allocate string and copy */
-
- /* look for tokens separated by semi-colons (;) or colons (:) */
-
- tp = token(path, PATH_SEPARATOR);
- while (tp != NULL)
- {
- strcpy(fpath, tp);
- len = strlen(fpath) - 1;
-
- /* make sure there is a separator between path and filename */
-
- if (!strchr(FILE_SEPARATOR, fpath[len]))
- fpath[++len] = "/";
-
- strcpy(&fpath[len+1], fname);
- if ( !access(fpath, RD_PERM)) )
- break;
-
- tp = token(NULL, PATH_SEPARATOR);
- }
- tfree(path);
- }
- #endif
-
-
- /*
- * make - guts of the make command
- * - make all pre-requisites, and if necessary, build target
- *
- * returns -1 target was already up to date w.r.t. pre-requisites
- * 0 target has not been built
- * 1 target is now built (and up to date)
- */
- make(targname, worry)
- char *targname;
- int worry; /* if set, it is an error to NOT build this */
- {
- REGISTER targptr targp;
- REGISTER fileptr *preqp;
- fileptr filep;
- long targtime;
- long preqtime;
-
- /* if recorded time of file is not default, we've already built it */
- filep = get_file(targname);
- if (filep && filep->ftime != MAXNEGTIME)
- return (-1);
-
- targp = get_target(targname); /* find the target node */
- if (targp == NULL)
- return (default_rule(targname, worry, 0));
-
- targtime = file_time(targname); /* keep actual time of current target */
-
- /* must build non-existant files, even with no pre-requisites */
- preqtime = MAXNEGTIME + 1;
-
- /* make all pre-requisites */
- preqp = targp->tpreq;
- while (*preqp)
- {
- make((*preqp)->fname, worry);
-
- /* keep track of newest pre-requisite */
- if (preqtime < (*preqp)->ftime)
- preqtime = (*preqp)->ftime;
-
- /* display as necessary */
- if (debug || (debug && (*preqp)->ftime > targtime))
- {
- display_prereq(targname, targtime, (*preqp)->fname,
- (*preqp)->ftime);
- }
-
- ++preqp;
- }
-
- if (targp->tshell == NULL) /* try default rules anyway */
- return (default_rule(targname, 0, force || preqtime > targtime));
- else if (force || preqtime > targtime)
- {
- if (touch) /* won't be set when `noexec' */
- touch_file(targname);
- else
- {
- add_metas("", "", targname);
- build(targp->tshell);
- }
-
- targp->tfile->ftime = (noexec) ? now : file_time(targname);
- return (1);
- }
-
- targp->tfile->ftime = targtime;
-
- return (-1);
- }
-
-
- /*
- * default_rule - try the .SUFFIXES when we don't have an explicit target
- * - if `worry' is set, it is an ERROR to NOT build this target
- * - `mustbuild' is set if make() has out-of-date prereq's
- * but no explicit shell rules
- */
- default_rule(targname, worry, mustbuild)
- char *targname;
- int worry;
- int mustbuild;
- {
- REGISTER targptr targp;
- REGISTER fileptr *preqp;
- fileptr filep;
- char *ext;
- char *basename;
- char *preqname;
- long targtime;
- long preqtime;
- int built;
- char suffrule[80];
-
- /* find the extension */
- ext = strrchr(targname, '.');
- if (ext == NULL)
- ext = targname + strlen(targname);
-
- /* find the base name */
- basename = tstrncpy(targname, ext - targname);
-
- targtime = file_time(targname);
-
- /* suffix_targ is used to (slightly) speed up this function */
- preqp = suffix_targ ? suffix_targ->tpreq : NULL;
- built = 0;
-
- while (preqp && *preqp && !built)
- {
- /* look for a default rule from SUFFIX to `ext' */
- strcat(strcpy(suffrule, (*preqp)->fname), ext);
- targp = get_target(suffrule); /* e.g. `.c.o' */
-
- if (targp != NULL)
- {
- /* found a rule; see if file exists */
- preqname = tstrcat(basename, (*preqp)->fname);
- preqtime = file_time(preqname);
-
- /*
- * don't bother recursive makes unless necessary
- * e.g. we have .c.o and .l.c, but also .l.o!
- * we want to use .l.o if a .c file does not exist
- */
- if (preqtime != MAXNEGTIME || mustbuild)
- built = make(preqname, 0);
-
- /* check if pre-req file exists and is newer */
- preqtime = file_time(preqname);
- if (preqtime > targtime || (mustbuild && built))
- {
- if (debug)
- display_prereq(targname, targtime, preqname, preqtime);
-
- if (touch) /* won't be set when `noexec' */
- touch_file(targname);
- else
- {
- add_metas(basename, preqname, targname);
- build(targp->tshell);
- }
- built = 1;
- }
- else if (debug && preqtime != MAXNEGTIME)
- display_prereq(targname, targtime, preqname, preqtime);
-
- tfree(preqname);
- }
-
- ++preqp; /* try next .SUFFIXES rule */
- }
-
-
- if (!built)
- {
- /* didn't find anything; try the default rule */
- targp = get_target(".DEFAULT");
- if (targp != NULL)
- {
- add_metas(basename, "", targname);
- build(targp->tshell);
- built = 1;
- }
- else if (targtime == MAXNEGTIME && worry)
- terror(1, tstrcat("Don't know how to make ", targname));
- }
-
- tfree(basename);
-
- /* record the current file time */
- if ((filep = get_file(targname)) != NULL)
- {
- filep->ftime = (built == 1 && noexec) ? now
- : file_time(targname);
- }
-
- return (built ? built : ((targtime == MAXNEGTIME) ? 0 : -1));
- }
-
-
- /*
- * add_metas - add symbols for $*, $< and $@
- */
- add_metas(basename, preqname, targname)
- char *basename;
- char *preqname;
- char *targname;
- {
- add_symbol("*", basename);
- add_symbol("<", preqname);
- add_symbol("@", targname);
- }
-
-
- /*
- * touch_file - set the MODIFICATION time of the file to NOW
- */
- touch_file(targname)
- char *targname;
- {
- REGISTER int handle;
- #ifndef MSDOS
- time_t timep[2];
-
- time(&timep[0]);
- timep[1] = timep[0];
- handle = utime(targname, timep);
- #else
- handle = utime(targname, NULL);
- #endif
- fputs("*** touching : ", stdout);
- puts(targname);
-
- if (handle == 0)
- return;
-
- /* create the file, if it did not exist */
- if (errno == ENOENT)
- {
- handle = open(targname, O_CREAT | O_TRUNC, S_IWRITE);
- if (handle != -1)
- {
- close(handle);
- return;
- }
- }
-
- perror("make");
- exit (1);
- }
-
-
- /*
- * build - process the shell commands
- */
- build(shellp)
- REGISTER shellptr *shellp;
- {
- REGISTER char **argv; /* argified version of scmd */
- int runst = 0; /* exec return status */
- char *scmd; /* command with symbols broken out */
- char *tcmd; /* copy of scmd for `tokenize' */
- char *mk; /* builtin make macro */
- char **shcp; /* pointer to shell command list */
- symptr symp; /* points to macro definition */
- #ifndef MSDOS
- char *format; /* for displaying error msg's */
- #else
- int resp_file; /* response file possible */
- char *cwd; /* current work directory */
- FILE *fd; /* temporary file (if needed) */
- char *fname, *comma; /* temporary name pointers (if needed) */
- int i;
- #endif
-
- symp = get_symbol("MAKE");
- mk = symp->svalue;
-
- #ifdef MSDOS
- cwd = getcwd(NULL, 1); /* where are we ? */
- #endif
-
- for (;*shellp != NULL && runst == 0;
- tfree(scmd), tfree(tcmd), tfree(argv), ++shellp)
- {
- /* breakout runtime symbols (e.g. $* $@ $<) */
- scmd = breakout((*shellp)->scmd);
-
- if (!(*shellp)->s_silent && !silent)
- puts(scmd);
-
- /* make a copy because tokenize litters '\0's */
- tcmd = tstrcpy(scmd);
- argv = tokenize(tcmd);
-
- #ifdef MSDOS
- /* check for .RESPONSE command */
- shcp = resp_cmds;
-
- for (resp_file = 0; !resp_file && *shcp; ++shcp)
- resp_file = equal(*shcp, argv[0]);
-
- if ( !noexec && resp_file && strlen(scmd) > 128 )
- { /* Create temporary response file */
- if ( (fname = tempnam("\TMP", "MAK")) )
- {
- fd = fopen(fname, "w");
-
- for ( i = 1; argv[i]; i++ )
- {
- for ( comma = argv[i];
- *comma && (comma = strchr(comma, ',')); argv[i] = comma )
- {
- *comma++ = '\0';
- fprintf(fd, "%s,\n", argv[i]);
- }
- fprintf(fd, "%s +\n", argv[i]);
- }
- fputc(';', fd);
- fputc('\n', fd);
- fclose(fd);
- argv[1] = tstrcat("@", fname);
- argv[2] = NULL;
- }
- }
- else
- resp_file = 0;
- #endif
-
- if ( equal(argv[0], mk) )
- {
- /* call ourselves recursively */
- new_make(argv);
- continue;
- }
-
- if (noexec)
- continue;
-
- /* any indirection MUST be handled by the shell */
- if (!(*shellp)->s_shell && strpbrk(scmd, "<|>"))
- (*shellp)->s_shell = 1;
- #ifdef MSDOS
- /* likewise, check for COMMAND.COM builtin commands */
-
- for (shcp = shell_cmds; !(*shellp)->s_shell && *shcp; ++shcp)
- (*shellp)->s_shell = equal(*shcp, argv[0]);
- #endif
- /* run without COMMAND.COM if possible, 'cause it uses RAM */
- if ( forceshell || (*shellp)->s_shell )
- runst = system(scmd);
- else
- runst = spawnvp(P_WAIT, argv[0], argv);
-
- #ifdef MSDOS
- chdir(cwd); /* back to work directory */
-
- if ( resp_file ) /* free temporary file argument */
- {
- remove(fname);
- tfree(argv[2]);
- free(fname);
- }
- #endif
-
- if (runst == 0)
- continue;
-
- /* uh-oh, an error */
- if (runst == -1)
- perror("make");
- #ifdef MSDOS
- itoa(runst, scmd, 10);
-
- if ( !single_ign && (ignore || (*shellp)->s_ignore) )
- strcat(scmd, " (ignored)");
- else if ( single_ign && !(ignore || (*shellp)->s_ignore) )
- strcat(scmd, " (target aborted)");
- terror(0, tstrcat("\n\n*** Error code ",scmd));
- putchar('\n');
- #else
- if ( !single_ign && (ignore || (*shellp)->s_ignore) )
- format = "(ignored)");
- else if ( single_ign && !(ignore || (*shellp)->s_ignore) )
- format = "(target aborted)");
- else
- format = "";
-
- sprintf(scmd, "\n\n*** Error code %d %s\n", runst, format);
- terror(0, scmd);
- #endif
- if (!single_ign && !ignore && !(*shellp)->s_ignore)
- exit(1);
- else if ( !single_ign )
- runst = 0;
- }
-
- #ifdef MSDOS
- free(cwd); /* free directory path space */
- #endif
- }
-
-
- /*
- * new_make - save current environment
- * - call make() recursively (actually main())
- * - clean up new environment
- * - restore environment
- */
- new_make(argv)
- char **argv;
- {
- targptr thead, tnext;
- fileptr fhead, fnext;
- symptr shead, snext;
- shellptr shhead, shnext;
- char **ttlist;
- long tnow;
- int i;
-
- /* save all the globals */
- thead = target_list;
- fhead = file_list;
- shead = symbol_list;
- shhead = shell_list;
- ttlist = tlist;
- tnow = now;
-
- /* count the arguments */
- for (i = 0; argv[i]; ++i);
-
- /* call ourselves recursively; this inherits flags */
- main(i, argv);
-
- /* we're back, so gotta clean up and dispose of a few things */
- while (target_list)
- {
- tnext = target_list->tnext;
- if (target_list->tpreq)
- tfree(target_list->tpreq);
- if (target_list->tshell)
- tfree(target_list->tshell);
- tfree(target_list);
- target_list = tnext;
- }
-
- while (file_list)
- {
- fnext = file_list->fnext;
- tfree(file_list->fname);
- tfree(file_list);
- file_list = fnext;
- }
-
- while (symbol_list)
- {
- snext = symbol_list->snext;
- tfree(symbol_list->sname);
- tfree(symbol_list->svalue);
- tfree(symbol_list);
- symbol_list = snext;
- }
-
- while (shell_list)
- {
- shnext = shell_list->slink;
- tfree(shell_list->scmd);
- tfree(shell_list);
- shell_list = shnext;
- }
-
- /* restore our original globals */
- target_list = thead;
- file_list = fhead;
- symbol_list = shead;
- shell_list = shhead;
- tlist = ttlist;
- now = tnow;
- }
-
-
- usage()
- {
- char **us_str;
- int i;
-
- for ( i = 1, us_str = usage_str; *us_str; puts(*us_str++), i++ )
- if ( !(i % 24) )
- {
- printf("Press key to continue...");
- getchar();
- }
-
- exit(1);
- }
-
-
- display_prereq(targname, targtime, preqname, preqtime)
- char *targname;
- long targtime;
- char *preqname;
- long preqtime;
- {
- printf("%s (%08lx) %s than %s (%08lx)\n",
- targname, targtime,
- (targtime < preqtime) ? "older" : "newer",
- preqname, preqtime);
- }
-
-
- long file_time(fname)
- char *fname;
- {
- REGISTER int handle;
- #ifdef MSDOS
- /*
- union
- {
- long ltime;
- struct
- {
- unsigned time;
- unsigned date;
- } s;
- } ftime;
- */
- struct stat sbuf;
- #else
- struct stat sbuf;
- #endif
-
- handle = open(fname, O_RDONLY);
- if (handle == -1)
- return (MAXNEGTIME);
-
- #ifdef MSDOS
- /*
- if (_dos_getftime(handle, &ftime.s.date, &ftime.s.time))
- ftime.ltime = MAXNEGTIME;
- */
- fstat(handle, &sbuf);
- #else
- fstat(handle, &sbuf);
- #endif
- close(handle);
-
- #ifdef MSDOS
- /*
- return (ftime.ltime);
- */
- return (sbuf.st_mtime);
- #else
- return (sbuf.st_mtime);
- #endif
- }
-
-
- /*
- * curr_time - return current time in same format as file_time()
- * - used with the `-n' option
- */
- long
- curr_time()
- {
- #ifndef MSDOS
- return (time(NULL));
- #else
- struct dosdate_t date;
- struct dostime_t time;
-
- _dos_getdate(&date);
- _dos_gettime(&time);
-
- return ((((long) (date.year-1980)<<9 | date.month<<5 | date.day) << 15)
- | (time.hour << 11 | time.minute << 5 | time.second >> 1) >> 1);
- #endif
- }
-
- #ifndef MSDOS
- int
- spawnvp(mode, path, args)
- int mode;
- char *path;
- char **args;
- {
- int pid = 0;
- union wait waitword;
-
- if (mode != P_OVERLAY)
- pid = fork();
-
- if (pid == 0)
- execvp(path, args);
-
- wait(&waitword);
- return (waitword.w_retcode);
- }
- #endif
-