5bb835f439
PR: 50953 Submitted by: Heiner Eichmann <h.eichmann@gmx.de>
483 lines
14 KiB
C
483 lines
14 KiB
C
--- src/smbmount.c.orig Sun Jun 9 09:58:43 2002
|
|
+++ src/smbmount.c Fri Apr 11 16:55:26 2003
|
|
@@ -16,6 +16,9 @@
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
+#include <sys/param.h>
|
|
+#include <errno.h>
|
|
+#include <poll.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
@@ -70,6 +73,9 @@
|
|
} UMOUNT_STRUCT;
|
|
static GSList *umountlist = NULL;
|
|
|
|
+void split_arguments(char * arguments, char * argv[], int * argnr, GSList ** strlist);
|
|
+char * storeInBuffer(const char * s, GSList ** strlist);
|
|
+void execvp_with_password(const char * path, char * const argv[], const char * passwd, GSList * strlist);
|
|
|
|
char suprompt[] = "Passw";
|
|
|
|
@@ -322,6 +328,7 @@
|
|
int pipe2_nok,pipe3_nok=1;
|
|
int sumount,argnr=-1,passw_lf;
|
|
char commandstr[MAXMNTCOMMANDL],commandstr1[MAXMNTCOMMANDL];
|
|
+ char num1[10], num2[10], num3[10], num4[10], tmp[MAXMNTCOMMANDL];
|
|
char opt_group[MAXMNTCOMMANDL];
|
|
char dummysmbpasswd[64];
|
|
/*#ifdef LINUX2_0 */
|
|
@@ -345,6 +352,7 @@
|
|
sumount=(supasswd!=NULL);
|
|
passw_lf=(*smbpasswd==0) && !linux2_0; /*smbmount 2.0.3 always waits for password,
|
|
even if called with -Uuser% or -N if server is in user level security*/
|
|
+ passw_lf=1;
|
|
if (sumount|| passw_lf)
|
|
if (pipe(fdstdin))
|
|
{
|
|
@@ -418,96 +426,53 @@
|
|
else
|
|
{
|
|
/* no sumount */
|
|
- if(linux2_0)
|
|
{
|
|
- argv[++argnr]="smbmount";
|
|
- argv[++argnr]=servicename;
|
|
- argv[++argnr]=mount_point;
|
|
- argv[++argnr]="-c";
|
|
- argv[++argnr]=clientname;
|
|
- argv[++argnr]="-I";
|
|
- argv[++argnr]=ipaddr;
|
|
- if (*group_name)
|
|
+ // bugfix: mount command might consist of more than one word (example: sudo mount_smbfs)
|
|
+ split_arguments(pref_get_smbmount_exe(), argv, &argnr, &strlist);
|
|
{
|
|
- argv[++argnr]="-D";
|
|
- argv[++argnr]=group_name;
|
|
- }
|
|
- argv[++argnr]="-U";
|
|
- argv[++argnr]=smbuser;
|
|
- argv[++argnr]="-f";sprintf(filemodestr,"%d",filemode);
|
|
- argv[++argnr]=filemodestr;
|
|
- argv[++argnr]="-d";sprintf(dirmodestr,"%d",dirmode);
|
|
- argv[++argnr]=dirmodestr;
|
|
- argv[++argnr]="-u";sprintf(uidstr,"%d",uid);
|
|
- argv[++argnr]=uidstr;
|
|
- argv[++argnr]="-g";sprintf(gidstr,"%d",gid);
|
|
- argv[++argnr]=gidstr;
|
|
- if (*smbpasswd==0)
|
|
- argv[++argnr]="-n";
|
|
- else
|
|
- {
|
|
- argv[++argnr]="-P";
|
|
- argv[++argnr]=smbpasswd;
|
|
- }
|
|
- argv[++argnr]=NULL;
|
|
- }
|
|
- else
|
|
- {
|
|
- /* linux 2.2/2.4 */
|
|
- argv[++argnr]=pref_get_smbmount_exe();
|
|
- argv[++argnr]=servicename;
|
|
- if (pref.v.smbmount_version>SMBMOUNT_204) argv[++argnr]=mount_point;
|
|
- if (pref.v.smbmount_version<SMBMOUNT_206)
|
|
- {
|
|
- /* 2.04/2.05 */
|
|
+ sprintf(num1,"%d", filemode);
|
|
+ sprintf(num2,"%d", dirmode);
|
|
+ sprintf(num3,"%d", uid);
|
|
+ sprintf(num4,"%d", gid);
|
|
+ strcpy(commandstr1, "//");
|
|
+ if (strlen(smbuser))
|
|
+ {
|
|
+ strcat(commandstr1, smbuser);
|
|
+ strcat(commandstr1, "@");
|
|
+ }
|
|
+ if (strlen(servicename) > 2)
|
|
+ strcat(commandstr1, servicename+2);
|
|
+ argv[++argnr]="-f";
|
|
+ argv[++argnr]=num1;
|
|
+ argv[++argnr]="-d";
|
|
+ argv[++argnr]=num2;
|
|
+ argv[++argnr]="-u";
|
|
+ argv[++argnr]=num3;
|
|
+ argv[++argnr]="-g";
|
|
+ argv[++argnr]=num4;
|
|
argv[++argnr]="-I";
|
|
- argv[++argnr]=ipaddr;
|
|
+ strcpy(tmp, ipaddr);
|
|
+ argv[++argnr]=tmp;
|
|
if (*group_name)
|
|
{
|
|
argv[++argnr]="-W";
|
|
- argv[++argnr]=group_name;
|
|
- }
|
|
- sprintf(userpasswd,"-U%s%%%s",smbuser,smbpasswd);
|
|
- argv[++argnr]=userpasswd;
|
|
- argv[++argnr]="-d0";
|
|
- if (pref.v.smbmount_version <SMBMOUNT_205)
|
|
- {
|
|
- argv[++argnr]="-c";
|
|
- argv[++argnr]=commandstr;
|
|
- sprintf(commandstr,"mount %s -f %d -d %d -u %d -g %d",
|
|
- /*escape_str_smbmnt(*/mount_point/*,&strlist)*/,filemode,dirmode,uid,gid);
|
|
- }
|
|
- if ( !is_empty_string(pref.v.smbmount_arg) )
|
|
- {
|
|
- }
|
|
- }
|
|
- else /*>=SMBMOUNT_206*/
|
|
- {
|
|
- argv[++argnr]="-o";
|
|
- argv[++argnr]=commandstr;
|
|
- sprintf(commandstr,"username=%s%%%s,fmask=%d,dmask=%d,uid=%d,gid=%d,ip=%s,debug=0",
|
|
- smbuser,smbpasswd,filemode,dirmode,uid,gid,ipaddr);
|
|
- if (*group_name)
|
|
- {
|
|
- strcat(commandstr,",workgroup=");
|
|
- strcat(commandstr,escape_str(group_name,&strlist));
|
|
+ argv[++argnr]= escape_str(group_name,&strlist);
|
|
}
|
|
if ( (port >= 0) && (port < 65536) )
|
|
{
|
|
- string_ncat(commandstr, ",port=", MAXMNTCOMMANDL);
|
|
- string_ncat(commandstr, port_str, MAXMNTCOMMANDL);
|
|
+ strcat(tmp, ":");
|
|
+ strcat(tmp, port_str);
|
|
}
|
|
if ( !is_empty_string(pref.v.smbmount_arg) )
|
|
{
|
|
- if ( pref.v.smbmount_arg[0] != ',' )
|
|
- string_ncat(commandstr, ",", MAXMNTCOMMANDL);
|
|
- string_ncat(commandstr, escape_str(pref.v.smbmount_arg,&strlist), MAXMNTCOMMANDL);
|
|
+ split_arguments(pref.v.smbmount_arg, argv, &argnr, &strlist);
|
|
}
|
|
}
|
|
+ argv[++argnr]=commandstr1;
|
|
+ argv[++argnr]=mount_point;
|
|
argv[++argnr]=NULL;
|
|
}
|
|
}
|
|
- slist_free_with_data(&strlist);
|
|
mountdat=g_malloc(sizeof(MOUNT_STRUCT));
|
|
if((pipe2_nok=pipe(fdstdout))|| (pipe3_nok=pipe(fdstderr))||
|
|
(mountdat->childpid =fork())== -1)
|
|
@@ -521,7 +486,6 @@
|
|
g_print(_("smbmount pipe,fork error\n"));
|
|
return;
|
|
}
|
|
-
|
|
if (!mountdat->childpid)
|
|
{
|
|
close(fdstdout[0]);
|
|
@@ -536,7 +500,7 @@
|
|
if (sumount)
|
|
execvp("su",argv);
|
|
else
|
|
- execvp(pref_get_smbmount_exe(),argv);
|
|
+ execvp_with_password(argv[0], argv, smbpasswd, strlist);
|
|
write(STDERR_FILENO,notfound,sizeof(notfound)-1);
|
|
_exit(0);
|
|
}
|
|
@@ -547,9 +511,9 @@
|
|
else
|
|
{
|
|
i=0;
|
|
- while(argv[i+1])
|
|
+ while(argv[i])
|
|
{
|
|
- mountdat->arglist[i]=g_strdup(argv[i+1]);
|
|
+ mountdat->arglist[i]=g_strdup(argv[i]);
|
|
i++;
|
|
}
|
|
mountdat->arglist[i]=NULL;
|
|
@@ -611,46 +575,9 @@
|
|
}
|
|
else
|
|
{
|
|
- if(linux2_0)
|
|
- {
|
|
- if (*smbpasswd!=0) argv[argnr-1]=dummysmbpasswd;
|
|
- }
|
|
- else
|
|
- {
|
|
- if (pref.v.smbmount_version<SMBMOUNT_206)
|
|
- sprintf(userpasswd,"-U%s%%%s",smbuser,dummysmbpasswd);
|
|
- else
|
|
- {
|
|
- sprintf(commandstr,"username=%s%%%s,fmask=%d,dmask=%d,uid=%d,gid=%d,ip=%s,debug=0",
|
|
- smbuser,dummysmbpasswd,filemode,dirmode,uid,gid,ipaddr);
|
|
- if (*group_name){
|
|
- strcat(commandstr,",workgroup=");
|
|
- strcat(commandstr,group_name);
|
|
- }
|
|
- if ( (port >= 0) && (port < 65536) )
|
|
- {
|
|
- string_ncat(commandstr, ",port=", MAXMNTCOMMANDL);
|
|
- string_ncat(commandstr, port_str, MAXMNTCOMMANDL);
|
|
- }
|
|
- if ( !is_empty_string(pref.v.smbmount_arg) )
|
|
- {
|
|
- if ( pref.v.smbmount_arg[0] != ',' )
|
|
- string_ncat(commandstr, ",", MAXMNTCOMMANDL);
|
|
- string_ncat(commandstr, escape_str(pref.v.smbmount_arg,&strlist), MAXMNTCOMMANDL);
|
|
- }
|
|
- }
|
|
- if (passw_lf)
|
|
- {
|
|
- usleep(50000);
|
|
- close(fdstdin[0]);
|
|
- if (!waitpid(mountdat->childpid,NULL,WNOHANG))
|
|
- write(fdstdin[1], "\n",1);
|
|
+ log_execvp_str(argv[0],argv);
|
|
close(fdstdin[1]);
|
|
}
|
|
- }
|
|
-
|
|
- log_execvp_str(pref_get_smbmount_exe(),argv);
|
|
- }
|
|
mountlist=g_slist_append(mountlist,mountdat);
|
|
mountdat->linepos=0; mountdat->linepos2=0;
|
|
mountdat->linenum=0;
|
|
@@ -901,17 +828,13 @@
|
|
}
|
|
else
|
|
{
|
|
- argv[0]=smb ? "smbumount":"umount";
|
|
- argv[1]=mount_point;
|
|
+ // bugfix: mount command might consist of more than one word (example: sudo mount_smbfs)
|
|
+ int argnr = -1;
|
|
+ split_arguments(pref_get_smbumount_exe(), argv, &argnr, &strlist);
|
|
if ( !is_empty_string(pref.v.smbumount_arg) )
|
|
- {
|
|
- argv[2] = pref.v.smbumount_arg;
|
|
- argv[3] = NULL;
|
|
- }
|
|
- else
|
|
- {
|
|
- argv[2]=NULL;
|
|
- }
|
|
+ split_arguments(pref.v.smbumount_arg, argv, &argnr, &strlist);
|
|
+ argv[++argnr]=mount_point;
|
|
+ argv[++argnr] = NULL;
|
|
}
|
|
if((pipe2_nok=pipe(fdstdout))|| (pipe3_nok=pipe(fdstderr))||
|
|
(childpid =fork())== -1)
|
|
@@ -938,7 +861,7 @@
|
|
execvp("su",argv);
|
|
}
|
|
else
|
|
- execvp(smb ? pref_get_smbumount_exe():"umount",argv);
|
|
+ execvp_with_password(argv[0], argv, "", strlist);
|
|
write(STDERR_FILENO,notfound,sizeof(notfound)-1);
|
|
_exit(0);
|
|
}
|
|
@@ -958,7 +881,7 @@
|
|
gui_log_window_insert_string("*",0);
|
|
}
|
|
else
|
|
- log_execvp_str(smb ? pref_get_smbumount_exe():"umount",argv);
|
|
+ log_execvp_str(argv[0], argv);
|
|
mountdat=g_malloc(sizeof(UMOUNT_STRUCT));
|
|
umountlist=g_slist_append(umountlist,mountdat);
|
|
mountdat->childpid=childpid;
|
|
@@ -1015,6 +938,198 @@
|
|
slist_free_with_data(&umountlist);
|
|
}
|
|
|
|
+void split_arguments(char * arguments, char * argv[], int * argnr, GSList ** strlist)
|
|
+{
|
|
+ char * c = argv[++*argnr] = storeInBuffer(arguments, strlist);
|
|
+ while(c = strchr(c, ' '))
|
|
+ {
|
|
+ char *d = c+1;
|
|
+ while(*d && *d == ' ')
|
|
+ d++;
|
|
+ *c = 0;
|
|
+ c = d;
|
|
+ if (!*c)
|
|
+ break;
|
|
+ argv[++*argnr] = storeInBuffer(c, strlist);
|
|
+ }
|
|
+}
|
|
+
|
|
+char * storeInBuffer(const char * s, GSList ** strlist)
|
|
+{
|
|
+ int n;
|
|
+ char * ss;
|
|
+
|
|
+ if (*s==0) return 0;
|
|
+ n = strlen(s);
|
|
+ ss=g_malloc(n+1);
|
|
+ strcpy(ss, s);
|
|
+ *strlist=g_slist_append(*strlist,ss);
|
|
+ return ss;
|
|
+}
|
|
+
|
|
+
|
|
+// this looks like a global variable. But each forked execvp_with_password
|
|
+// process has one copy of it. So it as a process local varible storing the
|
|
+// process ID of the forked child process, which actaully execs mount_smbfs
|
|
+int _childPid = 0;
|
|
+
|
|
+// called, if the child proces is killed. Kills its child process as well
|
|
+void stopMountSignalHandler (int sig)
|
|
+{
|
|
+ kill(_childPid, SIGINT);
|
|
+ waitpid(_childPid, 0, WUNTRACED);
|
|
+ _exit(0);
|
|
+}
|
|
+
|
|
+// replaces execvp to call mount_smbfs. If mount smbfs asks for a password, it is provided.
|
|
+// This can not be sent to stdin, because BSD gets the password directly from the terminal.
|
|
+// Therfore another process with a pseudo terminal is created.
|
|
+void execvp_with_password(const char * path, char * const argv[], const char * passwd, GSList *strlist)
|
|
+{
|
|
+ int master, i;
|
|
+ char terminal[MAXPATHLEN] = "";
|
|
+ char * pw = NULL;
|
|
+ int slave;
|
|
+ char password[1024], result[1024];
|
|
+ char * passwordText = "password:";
|
|
+ int passwordTextLen = strlen(passwordText);
|
|
+ char * resp_pos = result;
|
|
+ int fdstderr[2];
|
|
+
|
|
+ // create a pipe to the child process for stderr. For stdout the pseudo terminal is used
|
|
+ if(pipe(fdstderr))
|
|
+ {
|
|
+ fdstderr[0] = 0;
|
|
+ fdstderr[1] = 0;
|
|
+ }
|
|
+
|
|
+ // create the child process and the pseudo terminal
|
|
+ _childPid = forkpty(&master, terminal, NULL, NULL);
|
|
+
|
|
+ if (_childPid < 0)
|
|
+ {
|
|
+ if (errno == ENOENT)
|
|
+ printf("Error: Out of ptys\n");
|
|
+ else
|
|
+ printf(result, "Error: Forkpty\n");
|
|
+ _exit(1);
|
|
+ }
|
|
+ else if (_childPid == 0)
|
|
+ {
|
|
+ // prepare stderr pipe
|
|
+ if (fdstderr[0])
|
|
+ {
|
|
+ close(fdstderr[0]);
|
|
+ dup2(fdstderr[1], STDERR_FILENO);
|
|
+ }
|
|
+
|
|
+ // prepare the pseudo terminal
|
|
+ close(master);
|
|
+ slave = open(terminal, O_RDWR);
|
|
+ if (slave < 0)
|
|
+ {
|
|
+ printf("open() failed: %s", strerror(errno));
|
|
+ kill(_childPid, SIGINT);
|
|
+ waitpid(_childPid, 0, WUNTRACED);
|
|
+ _exit(1);
|
|
+ }
|
|
|
|
+ // launch application (mount_smbfs)
|
|
+ execvp(path, argv);
|
|
+ printf("error: %d (%s)\n", errno, strerror(errno));
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // prepare the stderr pipe
|
|
+ if (fdstderr[1])
|
|
+ close(fdstderr[1]);
|
|
|
|
+ // install the SIGIN (ctrl-c) handler
|
|
+ if (signal(SIGINT, stopMountSignalHandler) == SIG_ERR)
|
|
+ printf("error: can not install SIGINT handler\n");
|
|
+ errno = 0;
|
|
+ *resp_pos = 0;
|
|
+
|
|
+ // main loop: wait for childs response
|
|
+ while (!errno)
|
|
+ {
|
|
+ // prepare a poll, wich waits for output from the pseudo terminal and from stderr
|
|
+ int pollnum = 1;
|
|
+ struct pollfd polldat[2];
|
|
+ polldat[0].fd = master;
|
|
+ polldat[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
|
|
+ if (fdstderr[0])
|
|
+ {
|
|
+ pollnum = 2;
|
|
+ polldat[1].fd = fdstderr[0];
|
|
+ polldat[1].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
|
|
+ }
|
|
+
|
|
+ // sleep until the child terminates or sends something
|
|
+ if (poll(polldat, pollnum, 1000) < 0)
|
|
+ break;
|
|
|
|
+ // response from childs stderr?
|
|
+ if (pollnum == 2 && polldat[1].revents)
|
|
+ {
|
|
+ // read response and send it to this process' stderr. It is connected
|
|
+ // with another pipe with the main process!
|
|
+ char s[1024];
|
|
+ int i = read(fdstderr[0], s, 1024);
|
|
+ if (errno)
|
|
+ break;
|
|
+ if (i > 0)
|
|
+ {
|
|
+ s[i] = 0;
|
|
+ write(STDERR_FILENO, s, i);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // response from childs stdout?
|
|
+ if (polldat[0].revents)
|
|
+ {
|
|
+ // read response and send it to this process' stdout. It is connected
|
|
+ // with another pipe with the main process. If the string 'password'
|
|
+ // was send, provide the password
|
|
+ char c;
|
|
+ if (read(master, &c, 1) <= 0 || errno)
|
|
+ break;
|
|
+ if (resp_pos - result < sizeof(result))
|
|
+ *resp_pos++ = c;
|
|
+ *resp_pos = 0;
|
|
+ if (c == '\n')
|
|
+ {
|
|
+ printf("%s", result);
|
|
+ resp_pos = result;
|
|
+ }
|
|
+ *resp_pos = 0;
|
|
+ if (resp_pos - result >= passwordTextLen && !strcasecmp(resp_pos-passwordTextLen, passwordText))
|
|
+ {
|
|
+ // prepare the password and send it through the pseudo terminal
|
|
+ strcpy(password, passwd);
|
|
+ strcat(password, "\n");
|
|
+ resp_pos = result;
|
|
+ *resp_pos = 0;
|
|
+ write(master, password, strlen(password));
|
|
+ }
|
|
+ }
|
|
+ // if the child is dead, end main loop
|
|
+ if (waitpid(_childPid,NULL,WNOHANG))
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // if there is unsend response, send it to the main process
|
|
+ printf("%s", result);
|
|
+
|
|
+ // free resources
|
|
+ if (fdstderr[0])
|
|
+ close(fdstderr[0]);
|
|
+ close(master);
|
|
+ slist_free_with_data(&strlist);
|
|
+
|
|
+ // get childs return code to avoid zombies
|
|
+ waitpid(_childPid, 0, WUNTRACED);
|
|
+ _exit(0);
|
|
+ }
|
|
+ _exit(-1); // can not be reached
|
|
+}
|