Converting an old program
I have an old dos program of mine which I want to convert to linux. Its in Borland C. It creates a unique name based on the systems current date and time not an offset from 1970 but the current MMDDYY HHMMSS. I beleive tis best left as C but some of the routines I remember being Borland specific would need to be rewritten. This is a first effort for me in Unix and I would like help from the list as I can not afford books at this time. Though once I used it stand alone its best called from a script which passes it file names one at a time. Here is the Code sorry about the line length. /* ------------------------------------------------------------------------- */ /* UNIQUENA a program to rename a given file or set thereof by encoding the */ /* date and time from the system. Should the time be zero that section will */ /* rerun until a non zero result is obtained. This program will handle wild */ /* cards and multiple files listed. see OVERWRIT & PUBLIC */ /* prog by Carl William Spitzer IV */ /* ------------------------------------------------------------------------- */ /*struct date */ /* int da_year; current year */ /* char da_day; day of the month */ /* char da_mon; month (1 = Jan) */ /* */ /*struct time */ /* unsigned char ti_min; minutes */ /* unsigned char ti_hour; hours */ /* unsigned char ti_hund; hundredths of seconds */ /* unsigned char ti_sec; seconds */ /* ----------------------- function prototype section ---------------------- */ void main( int argc, char *argv[] ); void UniqueName( char *); /* ------------------------ preprocessor statements ------------------------ */ #include <dos.h> #include <dir.h> #include <stdio.h> #include <alloc.h> #include <stdlib.h> #include <string.h> #include <process.h> /* -------------------- global variables and structures -------------------- */ /* ----------------------- main and other functions ------------------------ */ void main (int argc, char *argv[]) { char *OldName; char *NewName; char drive[MAXDRIVE]; char dir[MAXDIR]; char file[MAXFILE]; char ext[MAXEXT]; int flags; if (argc<1) { printf("Usage: %s filespec\n",argv[0]); exit(1); } flags = 0; OldName = argv[1]; do { UniqueName(NewName); flags=fnsplit(OldName,drive,dir,file,ext); /* split the string to separate elems */ fnmerge(NewName,drive,dir,NewName,ext); /* merge everything into one string */ flags = ( (rename(OldName, NewName) == 0) ? 0 : 1); } while (flags == 1); } void UniqueName( char * NN) { struct date Today; struct time Now; div_t x,y; char Buffer[20]; gettime (&Now); getdate (&Today); x = div( (Today.da_year-1980) * Today.da_day * Today.da_mon,2); do y = div(Now.ti_hour * Now.ti_min * Now.ti_sec + Now.ti_hund,2); while (y.quot == 0); sprintf (Buffer,"%04X%04X",x.quot,y.quot); strcpy(NN, Buffer); } -- ___ _ _ _ ____ _ _ _ | | | | [__ | | | |___ |_|_| ___] | \/
Carl William Spitzer IV wrote:
I have an old dos program of mine which I want to convert to linux. Its in Borland C. It creates a unique name based on the systems current date and time not an offset from 1970 but the current MMDDYY HHMMSS.
I beleive tis best left as C but some of the routines I remember being Borland specific would need to be rewritten. This is a first effort for me in Unix and I would like help from the list as I can not afford books at this time.
There isn't a lot to it, Carl - you can start off with just trying to compile it: gcc -Wall <sourcefile> -o <binary> it won't compile as you have some includes that don't exist on a typical linux system: dos.h, dir.h, process.h, alloc.h. Next you'll have to look at uniquename() and fix you retrieve time and date - check time.h for some clues. fnsplit() and fnmerge() don't exist either, so you'll have to find equivalents or write them yourself. /Per Jessen, Zürich
On Sun, 2006-08-06 at 09:29 +0200, Per Jessen wrote:
Carl William Spitzer IV wrote:
I have an old dos program of mine which I want to convert to linux. Its in Borland C. It creates a unique name based on the systems current date and time not an offset from 1970 but the current MMDDYY HHMMSS.
I beleive tis best left as C but some of the routines I remember being Borland specific would need to be rewritten. This is a first effort for me in Unix and I would like help from the list as I can not afford books at this time.
There isn't a lot to it, Carl -
you can start off with just trying to compile it:
gcc -Wall <sourcefile> -o <binary>
it won't compile as you have some includes that don't exist on a typical linux system: dos.h, dir.h, process.h, alloc.h.
Next you'll have to look at uniquename() and fix you retrieve time and date - check time.h for some clues. fnsplit() and fnmerge() don't exist either, so you'll have to find equivalents or write them yourself.
That is why I asked I do not have any unix programming books to study. the file name split and merge routines should be simple string routines but the includes I can not begin to guess at. Recommendations online?? CWSIV
Carl William Spitzer IV wrote:
it won't compile as you have some includes that don't exist on a typical linux system: dos.h, dir.h, process.h, alloc.h.
Next you'll have to look at uniquename() and fix you retrieve time and date - check time.h for some clues. fnsplit() and fnmerge() don't exist either, so you'll have to find equivalents or write them yourself.
That is why I asked I do not have any unix programming books to study.
You don't need any books - the man pages will tell you everything you need to know.
the file name split and merge routines should be simple string routines but the includes I can not begin to guess at.
Just remove the ones you don't have, then see what fails to compile. It's a trial-and-error exercise. Of course, Jerry has already mentioned mkstemp which is the correct solution. /Per Jessen, Zürich
On Sun, 2006-08-06 at 20:31 +0200, Per Jessen wrote:
Carl William Spitzer IV wrote:
it won't compile as you have some includes that don't exist on a typical linux system: dos.h, dir.h, process.h, alloc.h.
Next you'll have to look at uniquename() and fix you retrieve time and date - check time.h for some clues. fnsplit() and fnmerge() don't exist either, so you'll have to find equivalents or write them yourself.
That is why I asked I do not have any unix programming books to study.
You don't need any books - the man pages will tell you everything you need to know.
the file name split and merge routines should be simple string routines but the includes I can not begin to guess at.
Just remove the ones you don't have, then see what fails to compile. It's a trial-and-error exercise.
Of course, Jerry has already mentioned mkstemp which is the correct solution.
its not a tmp file program its a renaming program so mkstemp does not solve the problem. -- _______ _______ _______ __ / ____\ \ / / ____|_ _\ \ / / | | \ \ /\ / / (___ | | \ \ / / | | \ \/ \/ / \___ \ | | \ \/ / | |____ \ /\ / ____) |_| |_ \ / \_____| \/ \/ |_____/|_____| \/ | \ /|\ || |\ / |~~\ /~~\ /~~| //~~\ | \ / | \ || | X |__/| || |( `--. |__ | | \| \_/ / \ | \ \__/ \__| \\__/
On Sunday 06 August 2006 9:57 pm, Carl William Spitzer IV wrote:
its not a tmp file program its a renaming program so mkstemp does not solve the problem. yes it does. Your program renames the program with a unique name. mkstemp() creates a file with a unique name. All you need to do is remove the file created by mkstemp. I had some old code I was porting with the old Unix tempnam() deprecated functions, so I updated my code. This program should do pretty much what yours is supposed to do. Note that the file name could be a full path, a relative path (foo/bar/fubar.c) or simply a filename.
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv) { char newname[256]; char *oldname = argv[1]; char *ext; char *relp; char thispath[256]; int fd, rc; char cmd[128]; if (argc != 2) { fprintf(stderr, "Usage maketemp <filename>\n"); exit(-1); } ext = strrchr(oldname, '.'); if (oldname[0] == '/') { /* we have full path */ strcpy(thispath, oldname); /* copy path */ relp = strrchr(thispath, '/'); /* locate last '/' */ relp[0] = '\0'; /* truncate */ } else { /* We have a relative path or bare filename use current directory */ if (getcwd(thispath, sizeof(thispath)) == NULL) { perror("getcwd"); return -1; } if (strchr(oldname, '/')) { strcat(thispath, "/"); /* Need this when oldname has a '/' */ strcat(thispath, oldname); relp = strrchr(thispath, '/'); /* locate last '/' */ relp[0] = '\0'; /* truncate */ } } /* at this point, thispath contains the directory portion or current directory */ sprintf(newname, "%s/XXXXXX", thispath); printf("Creating file:%s\n", newname); fd = mkstemp(newname); if (fd < 0) { perror("mkstemp"); exit(-1); } sprintf(cmd, "ls -l \"%s\"", newname); system(cmd); close(fd); unlink(newname); /* remove the file created by mkstemp */ system(cmd); /* just do an ls -l */ if (ext != NULL) { strcat(newname, ext); /* Add extension */ } printf("renaming %s to :%s\n", oldname, newname); sprintf(cmd, "ls -l \"%s\"", newname); if (rename(oldname, newname) == -1) { perror("rename"); return -1; } system(cmd); /* just do an ls -l */ return 0; } -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Sat, 05 Aug 2006 20:14:24 -0700 Carl William Spitzer IV <cwsiv@myrealbox.com> wrote:
/*struct date */ /* int da_year; current year */ /* char da_day; day of the month */ /* char da_mon; month (1 = Jan) */ /* */ /*struct time */ /* unsigned char ti_min; minutes */ /* unsigned char ti_hour; hours */ /* unsigned char ti_hund; hundredths of seconds */ /* unsigned char ti_sec; seconds */ /* ----------------------- function prototype section ---------------------- */ void main( int argc, char *argv[] ); void UniqueName( char *); /* ------------------------ preprocessor statements ------------------------ */ #include <dos.h> #include <dir.h> #include <stdio.h> #include <alloc.h> #include <stdlib.h> #include <string.h> #include <process.h> /* -------------------- global variables and structures -------------------- */
/* ----------------------- main and other functions ------------------------ */ void main (int argc, char *argv[]) { char *OldName; char *NewName; char drive[MAXDRIVE]; char dir[MAXDIR]; char file[MAXFILE]; char ext[MAXEXT]; int flags;
if (argc<1) { printf("Usage: %s filespec\n",argv[0]); exit(1); }
flags = 0; OldName = argv[1];
do { UniqueName(NewName); flags=fnsplit(OldName,drive,dir,file,ext); /* split the string to separate elems */ fnmerge(NewName,drive,dir,NewName,ext); /* merge everything into one string */ flags = ( (rename(OldName, NewName) == 0) ? 0 : 1); } while (flags == 1); }
void UniqueName( char * NN) { struct date Today; struct time Now; div_t x,y; char Buffer[20];
gettime (&Now); getdate (&Today);
x = div( (Today.da_year-1980) * Today.da_day * Today.da_mon,2); do y = div(Now.ti_hour * Now.ti_min * Now.ti_sec + Now.ti_hund,2); while (y.quot == 0); sprintf (Buffer,"%04X%04X",x.quot,y.quot); strcpy(NN, Buffer); } The date/time structure can be replaced by 'struct tm' in time.h (as Per mentioned). Getttime and getdate can be replaced by a call to time(3) which returns a time_t, then localtime(3) fills struct tm: time_t now; struct tm today; now = time(); localtime(&today);
Also look at the strftime(3) function to format the time/date. The DOS filespec contains the drive letter (eg c:), the path, and the filename. The Linux functions, dirname(3) and basename(3) should suffice in splitting the filename from the path. That leaves the extension. You can use the strrchr(3) funtion to locate the period. Remember, Unix names do not require an extension. But, a much simpler way to do this is to use the mkstemp(3) function. This function will also create a new file. The above code can effectively be: #include <stdio.h> #include <stdlib.h> #include <unistd.h> /* for close */ #include <libgen.h> int main(int argc, char **argv) { char *OldName; char *OPath. char NewName[256]; inf fd; if (argc<1) { printf("Usage: %s filespec\n",argv[0]); exit(1); } OldName = argv[1]; OPath = strdup(OldName); OPath = dirname(OPath); /* get path */ : strcpy(NewName, OPath); strcat(NewName, XXXXXX); /* Add template */ fd = mkstemp(NewName); if (fd < 0) { /* error here */ } close(fd); unlink(NewName); if (rename(NewName, OldName) < 0) { /* error here */ } return 0; } -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
I just want to add that using date and time today on fast multi-tasking systems will not give you the uniqueness you need. The mkstemp(3) function will give you a guaranteed unique name. Note that in my quick and dirty example, I did not add the file extension. If you do need to add the extension, do it after the mkstemp() call since the XXXXXX template must be the last 6 characters. You can easily do this: char *ext; ext = strrchr(OldName, '.'); : /* after mkstemp but before rename */ if (ext != NULL) strcat(NewNanme, ext); -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Sun, 2006-08-06 at 08:39 -0400, Jerry Feldman wrote:
I just want to add that using date and time today on fast multi-tasking systems will not give you the uniqueness you need. The mkstemp(3) function will give you a guaranteed unique name.
Note that in my quick and dirty example, I did not add the file extension. If you do need to add the extension, do it after the mkstemp() call since the XXXXXX template must be the last 6 characters. You can easily do this: char *ext; ext = strrchr(OldName, '.'); : /* after mkstemp but before rename */ if (ext != NULL) strcat(NewNanme, ext);
On a fast system I would simply adapt to find of the newname exists and loop back to make a new one. Strangely enough running the old exe works if I use it with wine in a loop so at the binary level there is some function. wine uniquena.exe $i This may be fun after all. -- ___ _ _ _ ____ _ _ _ | | | | [__ | | | |___ |_|_| ___] | \/
On Sun, 06 Aug 2006 10:29:47 -0700 Carl William Spitzer IV <cwsiv@myrealbox.com> wrote:
On a fast system I would simply adapt to find of the newname exists and loop back to make a new one. Strangely enough running the old exe works if I use it with wine in a loop so at the binary level there is some function. Actually that won't work because it is not atomic. Unix has long had tempname functions. These have been replaced by mkstemp().
Remember, Linux is a multi-tasking system and the time functions are generally not granular enough. (There are other time functions that are more higher grained) than time(). -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Sun, 2006-08-06 at 15:24 -0400, Jerry Feldman wrote:
On Sun, 06 Aug 2006 10:29:47 -0700 Carl William Spitzer IV <cwsiv@myrealbox.com> wrote:
On a fast system I would simply adapt to find of the newname exists and loop back to make a new one. Strangely enough running the old exe works if I use it with wine in a loop so at the binary level there is some function. Actually that won't work because it is not atomic. Unix has long had tempname functions. These have been replaced by mkstemp().
Remember, Linux is a multi-tasking system and the time functions are generally not granular enough. (There are other time functions that are more higher grained) than time().
Looks like strftime with individual parameters for hour minute second month day and year will do if I pass them one at a time and convert to integer with atoi. Then I can perform the relavant function and use formatting in sprintf to convert automatically to string. compiles ok but I am getting some errors but Ill cover that later when I double check the run time. -- ___ _ _ _ ____ _ _ _ | | | | [__ | | | |___ |_|_| ___] | \/
On Sun, 06 Aug 2006 10:29:47 -0700 Carl William Spitzer IV <cwsiv@myrealbox.com> wrote:
On Sun, 2006-08-06 at 08:39 -0400, Jerry Feldman wrote:
I just want to add that using date and time today on fast multi-tasking systems will not give you the uniqueness you need. The mkstemp(3) function will give you a guaranteed unique name.
Note that in my quick and dirty example, I did not add the file extension. If you do need to add the extension, do it after the mkstemp() call since the XXXXXX template must be the last 6 characters. You can easily do this: char *ext; ext = strrchr(OldName, '.'); : /* after mkstemp but before rename */ if (ext != NULL) strcat(NewNanme, ext);
On a fast system I would simply adapt to find of the newname exists and loop back to make a new one. Strangely enough running the old exe works if I use it with wine in a loop so at the binary level there is some function.
wine uniquena.exe $i
This may be fun after all. Your program would also run under dosemu. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
participants (3)
-
Carl William Spitzer IV
-
Jerry Feldman
-
Per Jessen